'''
添加页面操作关键字
'''
from selenium import webdriver
from Lib.common.chrome_options import Options
from Lib.common.ui_log import error_log, normal_log
# 设置显示等待
from selenium.webdriver.support.wait import WebDriverWait
# 判断是否是否可见
from selenium.webdriver.support import expected_conditions
# 鼠标相关操作
from selenium.webdriver.common.action_chains import ActionChains
from Lib.common.common_function import *
from selenium.webdriver.common.keys import Keys
from time import sleep
import time
import os
import sys
import pytest
import allure
from Tools.environment import Environment


class KeyWords:
    '''
      页面元素相关操作的封装
    '''
    # 获取url，公共连接  82
    url = Environment().system_env()

    def __init__(self, driver):
        self.driver = driver

    def open(self, url):
        '''
        打开网页
        :param url:
        :param context:
        :return:
        '''
        normal_log().info('>>>打开网页{0}'.format(url))
        self.driver.get(url)

    def locator(self, args, context=None):
        '''
        查找元素
        :param context
        :param args:
        :return:
        '''
        # 设置显示等待
        try:
            WebDriverWait(self.driver, 3).until(expected_conditions.visibility_of_element_located(args))
            return self.driver.find_element(*args)
        except Exception as e:
            error_log().debug(e)
            try:
                args = ('xpath', '//div[@class="rz-message-box"]//span[contains(text(), "确定")]')
                WebDriverWait(self.driver, 3).until(expected_conditions.visibility_of_element_located(args))
            except Exception as e:
                error_log().debug('未出现返回弹窗')
            else:
                self.driver.find_element(*args).click()
            # 如果存在退出确定弹窗， 关闭对应的弹窗
            raise ValueError("{}元素查找失败".format(context))

    def locator_elements(self, args, context=None):
        '''
        查找满足条件的所有元素
        :param context
        :param args:
        :return:
        '''
        try:
            WebDriverWait(self.driver, 3).until(expected_conditions.visibility_of_element_located(args))
            return self.driver.find_elements(*args)
        except Exception as e:
            # 如果存在退出确定弹窗， 关闭对应的弹窗
            self.close_return_window()
            time.sleep(2)
            raise ValueError("{}元素查找失败".format(context))

    def quite(self):
        '''
        关闭浏览器
        :return:
        '''
        normal_log().info('退出浏览器成功')
        self.driver.quit()

    def input_value(self, args, text, context=None):
        '''
        为输入框输入在值
        :param args:
        :param text: 需要输入的值
        :param context:
        :return:
        '''
        try:
            with allure.step(f"{context}输入{text}"):
                self.locator(args, context).send_keys(text)
        except Exception as e:
            error_log().debug('>>>>>>>>>{0}'.format(e))
            raise ValueError("为{}元素传值失败".format(context))

    def click(self, args, context=None):
        '''
        点击某个元素
        :param args:
        :param context:
        :return:
        '''
        try:
            with allure.step(f"点击{context}"):
                self.locator(args, context).click()
        except Exception as e:
            error_log().debug('>>>>>>>>>>>>>>>>>>>{0}'.format(e))
            raise ValueError("{}元素点击失败".format(context))

    def wait(self, second):
        '''
        设置显示等待
        :return:
        '''
        if second and type(second) is int:
            with allure.step(f'sleep{second}'):
                sleep(second)
        else:
            raise ValueError("输入的时间不合法")

    def hover(self, args, context=None):
        '''
        设置鼠标悬停
        :param args:
        :param context:
        :return:
        '''
        try:
            with allure.step(f"鼠标悬停{context}"):
                element = self.locator(args, context)
                ActionChains(self.driver).move_to_element(element).perform()
        except Exception as e:
            error_log().debug('>>>>>>>>>>>>>>>>>>>{0}'.format(e))
            raise ValueError("hover{}元素失败".format(context))

    def js_click(self, args, context=None):
        '''
        使用js点击元素
        :param args:
        :param context:
        :return:
        '''
        try:
            with allure.step(f"点击{context}"):
                element = self.locator(args, context)
                js = 'arguments[0].click()'
                self.driver.execute_script(js, element)
        except Exception as e:
            error_log().debug('js点击{0}失败'.format(context))
            error_log().debug('>>>>>>>>>>>>>>>>>>>{0}'.format(e))
            raise ValueError("使用js点击{}元素失败".format(context))

    def get_text(self, args, context=None):
        '''
        获取元素的文本信息，用作断言
        :param args:
        :param context:
        :return:
        '''
        try:
            # 判断元素是否可见
            text_element = self.locator(args, context)
            if text_element.is_displayed():
                return text_element.text
            else:
                return text_element.get_attribute("innerText")
        except Exception as e:
            error_log().debug('>>>获取{0}文本信息失败'.format())
            error_log().debug('>>>{0}'.format(e))
            self.get_error_picture(context)
            raise ValueError("获取{}的文本信息失败".format(context))

    def get_error_picture(self, context=None):
        '''
        拍摄错误的图
        :param context: 图片名称
        :return:
        '''
        # 路径拼接
        str_name = time.strftime('%Y%m%d%H%M%S')
        path = get_path() + '/Data/error_picture/{0}{1}.png'.format(str_name, context)
        self.driver.save_screenshot(path)

    def clear_input(self, args, context=None):
        '''
        清空输入框
        :param args:
        :param context:
        :return:
        '''
        try:
            with allure.step(f'清空{context}'):
                self.locator(args=args, context=context).clear()
        except Exception as e:
            error_log().debug('>>>>>>清空操作失败')
            error_log().debug(e)
            self.driver.save_screenshot(context)
            raise e

    def drag_up_and_down(self, args, context=None):
        '''
        上下进行拖动
        :return:
        '''
        try:
            with allure.step(f'滑动页面到{context}'):
                element = self.locator(args=args, context=context)
                js = "arguments[0].scrollIntoView();"
                self.driver.execute_script(js, element)
        except Exception as e:
            error_log().debug('>>>>>将鼠标拖动到{}失败'.format(context))
            error_log().debug(e)
            raise e

    def upload_by_exe(self, args, context=None):
        '''
        非input元素的附件上传
        :return:
        '''
        try:
            with allure.step(f"{context}上传"):
                # 点击附件上传弹窗
                self.click(args=args, context=context)
                self.wait(2)
                # 执行对应的程序
                path = get_path() + '/Resource/file_exe/test.exe'
                os.system(path)
        except Exception as e:
            error_log().debug('>>>上传{}附件失败'.format(context))
            error_log().debug('>>>>>{}'.format(e))
            raise e

    def upload_file_to_input(self, args, context=None):
        '''
        input元素类型附件上传
        :param args:
        :param context:
        :return:
        '''
        try:
            normal_log().info('>>>>>上传附件')
            filename = get_path() + '/Resource/photo/auto_photo.png'
            self.locator(args, context).send_keys(filename)
        except Exception as e:
            error_log().debug('>>>>>上传{}附件失败'.format(context))
            error_log().debug('>>>>>>{}'.format(e))
            raise e

    def enter(self, args, context=None):
        '''
        模拟键盘回车操作
        :param args:
        :param context:
        :return:
        '''
        try:
            normal_log().info('>>>>>模拟键盘回车操作')
            self.locator(args, context).send_keys(Keys.ENTER)
        except Exception as e:
            error_log().debug('>>>>>{}回车操作失败'.format(context))
            error_log().debug('>>>>>>{}'.format(e))
            raise e

    def refresh(self):
        '''
        刷新当前页面
        :return:
        '''
        try:
            with allure.step('刷新当前页面'):
                self.driver.refresh()
        except Exception as e:
            error_log().debug('>>>>>刷新当前页面失败')
            error_log().debug('>>>>>>{}'.format(e))

    def move_mouse(self, args, context=None):
        '''
        鼠标移动操作
        :param args:
        :param context:
        :return:
        '''
        try:
            with allure.step(f'移动鼠标到{context}'):
                # 获得鼠标对象
                mouse_obj = ActionChains(self.driver)
                # 移动鼠标到指定的元素
                mouse_obj.move_to_element(self.locator(args=args, context=context)).perform()
        except Exception as e:
            error_log().debug('>>>>>移动鼠标到{}失败'.format(context))
            error_log().debug('>>>>>>{}'.format(e))

    def js_shrink_page(self, args, context=None):
        '''
        使用js缩小当前页面
        :param args:
        :param context:
        :return:
        '''
        try:
            normal_log().info('>>>>>>>>>>>>js缩小{0}'.format(context))
            # 根据传入的值，确定缩小比例
            js = 'document.body.style.zoom="{0}"'.format(args[0])
            self.driver.execute_script(js)
        except Exception as e:
            raise ValueError("页面缩放失败")

    def input_value_with_time(self, args, text: list, context=None):
        '''
        为时间输入框输入时间值
        :param args:
        :param text: 需要输入的值  时间格式 和
        :param context:
        :return:
        '''
        try:
            with allure.step(f"添加时间到{context}"):
                print(text)
                time_format = get_time(format_time=text[0], number=text[1])
                self.locator(args, context).send_keys(time_format)
        except Exception as e:
            error_log().debug('>>>>>>>>>{0}'.format(e))
            self.get_error_picture(context)
            raise ValueError("为{}元素传值失败".format(context))

    def close_return_window(self):
        '''
        关闭是否退出确认弹窗
        :return:
        '''
        try:
            args = ('xpath', '//div[@class="rz-message-box"]//span[contains(text(), "确定")]')
            self.driver.find_element(*args).click()
            time.sleep(3)
        except ValueError as e:
            error_log().debug('>>>>>>>>>>不存在确定退出弹窗')

    def element_is_exist(self, args, context=None):
        '''
        判断元素是否存在，存在返回True 否则返回FALSE
        :param args:
        :param text:
        :param context:
        :return:
        '''
        try:
            WebDriverWait(self.driver, 5).until(expected_conditions.presence_of_element_located(args))
        except Exception as e:
            normal_log().info('只存在一条数据')
            return False
        else:
            return True

    def drag_element(self, args, text=None, context=None):
        '''
        按住元素之后进行拖动
        :param text:  移动的长度
        :param args:
        :param context:
        :return:
        '''
        try:
            element = self.locator(args=args, context=context)
            ActionChains(self.driver).drag_and_drop_by_offset(element, 0, text).perform()
        except Exception as  e:
            normal_log().debug(e)
            normal_log().debug('拖动元素失败')


if __name__ == '__main__':
    # print(time.strftime('%Y-%m-%d %H:%M:%S'))
    # print(time.strptime('2021-07-26 17:12:52', '%Y-%m-%d %H:%M:%S'))
    # print(time.mktime(time.strptime('2021-07-26 17:12:52', '%Y-%m-%d %H:%M:%S')))
    print('a' * 100)
